import { Body, Controller, HttpException, HttpStatus, Ip, Post, Req } from '@nestjs/common';
import { DtoPipe } from '../../pipes/dto/dto.pipe';
import { Dto } from './dto';
import { CacheService } from '@app/cache';
import { AuthService } from './auth.service';
import * as dayjs from 'dayjs';
import { ConfigureService } from '@app/configure';
import { BaseController } from '../../base/base.controller';


@Controller('auth')
export class AuthController extends BaseController{
    constructor(
        private service:AuthService,
        private configure:ConfigureService,
        private cache:CacheService
    ) {
        super()
    }

    @Post('login')
    async login(@Body(new DtoPipe({skipMissingProperties : false, skipNullProperties : false})) dto:Dto, @Ip() ip, @Req() {locale}) {

        const { account, password, tenant } = dto

        let time = dayjs().unix()
        let nextDayTime = dayjs(dayjs().format('YYYY-MM-DD')).add(1, 'day').unix() //下一天整点
        const loginFailMaxCount = this.configure.get<number>('loginFailMaxCount')
        const loginCountKey = 'login.er.' + account + '.' + dayjs().format('YYMD')
        let loginCount = Number((await this.cache.get(loginCountKey)) || 0)
        if(loginCount >= loginFailMaxCount) return this.failRes(this.i18n.t(locale, 'moreThanLoginCount', [loginFailMaxCount]))

        
        let lockKey = 'login.' + account
        if(tenant) {
            lockKey += (':' + tenant)
        }

        const lock = await this.cache.set(lockKey, '', 10, 'NX')
        if(!lock) return ''

        let tenantId = 0

        if(tenant) {
            const tenantInfo = await this.service.db.tenant.findOne({name : tenant}, ['enable', 'id'])
            if(!tenantInfo || !tenantInfo.enable) return this.failRes(this.i18n.t(locale, 'accountDisabled'))
            tenantId = tenantInfo.id
        }

        const member = await this.service.verify(account, password, tenantId)
        if(!member) {
            this.cache.del(lockKey)
            this.cache.set(loginCountKey, loginCount + 1, nextDayTime - time)

            return this.failRes(this.i18n.t(locale, 'accountOrPwdError'))
        }

        if(!member.enable) return this.failRes(this.i18n.t(locale, 'accountDisabled'))

        const {accessToken, refreshToken, expire} = this.service.makeToken(member.id, time)

        if(loginCount > 0) {
            this.cache.del(loginCountKey)
        }

        this.cache.del(lockKey)

        this.service.updateLogin(member.id, time, ip)

        return this.successRes({
            accessToken,
            refreshToken,
            expire,
            name : member.name,
            super : member.super,
            belong : member.belong
        })
    }
}
